Skip to content

chore(menu-bar): change the shortcut modifier from the menu - #16

Merged
rbstp merged 2 commits into
masterfrom
feat/shortcut-modifier
Sep 5, 2026
Merged

rbstp merged 2 commits into
masterfrom
feat/shortcut-modifier

Conversation

@rbstp

@rbstp rbstp commented Sep 5, 2026 •

Copy link
Copy Markdown
Owner

Follows #15. Right-click the icon and Shortcut Modifier offers ⌃⌘, ⌥⌘, ⌃⌥ and ⌃⌥⌘, with
the one in force ticked. It changes the modifier every shortcut uses and keeps each key — which key
does what is taste, and defaults write already serves that; the modifier is the part that collides
with other software, and so the part worth changing without a restart.

The icon flashes green when a change takes and red when it does not, in which case nothing is stored
and the log names the combination and the app that already holds it.

What is not obvious here

The colour is drawn into the image, not tinted over it. A template image is a mask, so a colour
applied to one goes nowhere: a status item button ignores contentTintColor entirely. I found that
by screenshotting the real menu bar and counting pixels rather than by reading the docs.

All three move together or none does. The new combinations are claimed before the old ones are
released, so finding out that one belongs to another app costs nothing — the partial set is dropped
and the working shortcuts were never given up. Announcing a registration is therefore separate from
making it: claiming a set that may be abandoned a moment later must not put combinations in the log
that were unregistered before anyone could press one.

Whether the choice changes anything is decided by comparing combinations, not their text. What is
stored is however it was written (cmd+ctrl+h); what a rewrite produces is canonical
(ctrl+cmd+h). The same chord is then two different strings, and claiming a combination this process
already holds is refused — so a text comparison would flash red for the one case that cannot fail:
picking the modifier that is already ticked. Codex caught that one.

The choice is stored only if the configuration it was made against is still in force. It is read
on the agent's queue and applied on the main one, so a SIGHUP reload can land in between; its
reading is the newer intent, and the registrations are put back in step with it rather than
overwritten. Codex caught that one too.

Testing

Driven through the real menu on a live install, using AX to press the items and screencapture to
check the icon:

  • Submenu renders with the current modifier ticked.
  • Picking a different modifier registered all three, stored them, and those arrows then cycled focus.
    (Verified with ⇧⌘ before it was withdrawn from the menu, and with ⌃⌥⌘ after.)
  • Green flash confirmed: 268 green pixels in the icon, back to neutral after.
  • Refusal confirmed by having a second process claim ⌥⌘→ first — Heed logged ⌥⌘ is not free,
    stored nothing, and the previous shortcuts still worked. 303 red pixels, back to neutral after.
  • Picking the already-ticked modifier with the un-canonical stored spelling: green, and nothing
    logged. That is the case the first version got wrong.

166 unit tests, make check-package passes.

One note on what is offered

⌥⌘ is offered with a tooltip saying what it costs — moving between browser tabs — but it is not the
default. ⇧⌘ is not offered at all: with the arrow keys it is how a line is selected in every text
field on the system, which is too much to hand away from behind a tooltip. defaults write still
sets either for anyone who wants it.

Heed can only refuse a combination another app registered the same way. Nothing refuses one the
system reads directly, so combinations like those are taken quietly and a warning before the fact is
the only one possible.

Right-click the icon and Shortcut Modifier offers ⌃⌘, ⌥⌘, ⇧⌘, ⌃⌥ and ⌃⌥⌘, with
the one in force ticked. It changes the modifier every shortcut uses and keeps
each key: which key does what is a matter of taste that `defaults write` already
serves, while the modifier is the part that collides with other software, and so
the part worth being able to change without a restart.

The icon flashes green when a change takes and red when it does not, in which
case nothing is stored and the log names the combination and the app that
already holds it. The colour is drawn into the image rather than tinted over it.
A template image is a mask, so a colour applied to one goes nowhere -- a status
item button ignores `contentTintColor` entirely, which was measured against the
running app rather than assumed.

All three move together or none does. The new combinations are claimed before
the old ones are released, so discovering that one of them belongs to another
app costs nothing: the partial set is dropped, the working shortcuts were never
given up, and the log says only what is true. Announcing a registration is
therefore separate from making it -- claiming a set that may be abandoned a
moment later must not put combinations in the log that were unregistered before
anyone could press one.

Two things a lighter version of this would get wrong. Whether the choice changes
anything is decided by comparing combinations and not the text of them: what is
stored is however it was written, "cmd+ctrl+h", and what a rewrite produces is
canonical, "ctrl+cmd+h", so the very same chord reads as a change -- and
claiming a combination this process already holds is refused, which would report
a failure for the one case that cannot fail. And the choice is stored only if
the configuration it was made against is still the one in force, because it is
read on the agent's queue and applied on the main one; a reload arriving in
between is the newer intent, and its shortcuts are put back rather than
overwritten.

⇧⌘ and ⌥⌘ are offered with a tooltip saying what they cost -- selecting a line,
and moving between browser tabs -- and neither is the default. Heed can only
refuse a combination another app registered the same way; nothing refuses one
the system reads directly, so those two are taken quietly and a warning before
the fact is the only one there is.
@rbstp rbstp changed the title feat(menu-bar): change the shortcut modifier from the menu chore(menu-bar): change the shortcut modifier from the menu Sep 5, 2026
Command-Shift with the arrow keys is how a line is selected in every text field
on the system. A registered hotkey takes the combination away everywhere, and
nothing refuses it -- the system reads those directly rather than registering
them the way an app does -- so the menu would have been handing that away from
behind a tooltip, which is not a warning anyone reads.

`defaults write` still sets it for anyone who wants it. What is gone is only the
one-click way to lose line selection by accident.
@rbstp
rbstp merged commit fa6fd59 into master Sep 5, 2026
1 check passed
@rbstp
rbstp deleted the feat/shortcut-modifier branch September 5, 2026 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant